package com.zhenhao.xsq.data.api;

import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;

import com.blankj.utilcode.util.ActivityUtils;
import com.orhanobut.logger.Logger;
import com.zhenhao.xsq.application.AppConfig;
import com.zhenhao.xsq.data.api.support.ErrorThrowable;
import com.zhenhao.xsq.entity.BaseDataEntity;
import com.zhenhao.xsq.entity.BaseEntity;
import com.zhenhao.xsq.entity.LoginEntity;
import com.zhenhao.xsq.entity.UserInfoEntity;
import com.zhenhao.xsq.entity.login.UserEntity;
import com.zhenhao.xsq.ui.activity.login.LoginActivity;
import com.zhenhao.xsq.utils.SpSaveUtils;
import com.zhenhao.xsq.utils.ToastUtil;

import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Map;

import javax.inject.Inject;

import androidx.annotation.NonNull;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.RequestBody;
import retrofit2.adapter.rxjava2.HttpException;


/**
 * @author hu
 * @desc 对Request实体(不执行)在执行时所调度的线程，以及得到ResponseBody后根据retCode对Result进行进一步处理
 * @date 2017/5/31 16:56
 */
public class HttpAPIWrapper {
    /**
     * 给任何Http的Observable加上通用的线程调度器
     */
    private static final ObservableTransformer SCHEDULERS_TRANSFORMER = new ObservableTransformer
            () {
        @Override
        public ObservableSource apply(@NonNull Observable upstream) {
            return upstream.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
        }
    };
    private HttpApi mHttpAPI;

    @Inject
    public HttpAPIWrapper(HttpApi mHttpAPI) {
        this.mHttpAPI = mHttpAPI;
    }

    /**
     * 给任何Http的Observable加上在Service中运行的线程调度器
     */
    public static <T> ObservableTransformer<T, T> getSchedulerstransFormerToService() {
        return new ObservableTransformer<T, T>() {
            @Override
            public ObservableSource<T> apply(Observable<T> upstream) {
                return upstream.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers
                        .mainThread());
            }
        };
    }

    //需要额外的添加其他的参数进去，所以把原有的参数和额外的参数通过这个方法一起添加进去.
    private static Map addParams(Map<String, String> data) {
        //添加统一的参数的地方
        //// TODO: 2018/7/11 打印传的参数
        for (Map.Entry<String, String> entry : data.entrySet()) {
            Log.w("map", "Key = " + entry.getKey() + ", Value = " + entry.getValue());
        }
        return data;
    }

    private static RequestBody addp(String s1) {
        RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; " +
                "charset=utf-8"), s1);
        return body;
    }
    //get
//    @SuppressWarnings("unchecked")
//    public Observable<BaseEntity> get(Map data) {
//        return wrapper(mHttpAPI.get(addParams(data))).compose(SCHEDULERS_TRANSFORMER);
//    }

    //post
//    @SuppressWarnings("unchecked")
//    public Observable<BaseEntity> post(Map data) {
//        return wrapper(mHttpAPI.post(addParams(data))).compose(SCHEDULERS_TRANSFORMER);
//    }

    @SuppressWarnings("unchecked")
    public Observable<BaseDataEntity> userLogin(Map data) {
        return wrapper(mHttpAPI.userLogin(addParams(data))).compose(SCHEDULERS_TRANSFORMER);
    }

    @SuppressWarnings("unchecked")
    public Observable<BaseEntity> getCode(String code, String xmbh, Map data) {
        return wrapper(mHttpAPI.getCode(code, xmbh, addParams(data))).compose
                (SCHEDULERS_TRANSFORMER);
    }

    @SuppressWarnings("unchecked")
    public Observable<BaseEntity> userLoginOut(String token, Map data) {
        return wrapper(mHttpAPI.userLoginOut(token, addParams(data))).compose
                (SCHEDULERS_TRANSFORMER);
    }

    @SuppressWarnings("unchecked")
    public Observable<UserEntity> userInfo(Map data) {
        return wrapper(mHttpAPI.userInfo(addParams(data))).compose(SCHEDULERS_TRANSFORMER);
    }


    /**
     * 根据Http的response中关于状态码的描述，自定义生成本地的Exception
     *
     * @param resourceObservable
     * @param <T>
     * @return
     */
    private <T extends BaseEntity> Observable<T> wrapper(Observable<T> resourceObservable) {
        return resourceObservable.flatMap(new Function<T, ObservableSource<? extends T>>() {
            @Override
            public ObservableSource<? extends T> apply(@NonNull final T baseResponse) throws
                    Exception {
                return Observable.create(new ObservableOnSubscribe<T>() {
                    @Override
                    public void subscribe(@NonNull ObservableEmitter<T> e) throws Exception {
                        if (baseResponse.code == 200) {
                            e.onNext(baseResponse);
                        } else {
                            if (baseResponse.code == 500 || baseResponse.code == 100 ||
                                    baseResponse.code == 990) {
                                if (!"设备故障,请检查".equals(baseResponse.error)) {
                                    ToastUtil.showLong(baseResponse.error);
                                }
                            }
                            if (baseResponse.code == 991 || baseResponse.code == 992) {
                                // token失效跳登录//回到登录界面
                                ToastUtil.showLong("登录已失效，请重新登录");
                                SpSaveUtils.clearSp();
                                AppConfig.getInstance().startActivity(new Intent(AppConfig.getInstance(),
                                        LoginActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
                                ActivityUtils.finishAllActivities();
                            } else {
                                e.onError(new ErrorThrowable());
                            }
                        }
                    }
                });
            }
        }).doOnError(new Consumer<Throwable>() {
            @Override
            public void accept(@NonNull Throwable e) throws Exception {
                e.printStackTrace();
                String errorText = "请求失败";
                if (e instanceof retrofit2.adapter.rxjava2.HttpException) {
                    retrofit2.adapter.rxjava2.HttpException exception = (retrofit2.adapter.rxjava2.HttpException) e;
                } else if (e instanceof UnknownHostException) {
                    Logger.i("请打开网络");
                    errorText = "请打开网络";
                } else if (e instanceof SocketTimeoutException) {
                    Logger.i("请求超时");
                    errorText = "请求超时";
                } else if (e instanceof ConnectException) {
                    Logger.i("连接失败");
                    errorText = "连接失败";
                } else if (e instanceof retrofit2.adapter.rxjava2.HttpException) {
                    Logger.i("请求超时");
                    errorText = "请求超时";
                } else if (e instanceof ErrorThrowable) {
                    //自定义code异常捕捉
//                    Logger.i("code100");
                    return;
                } else {
                    Logger.i("请求失败");
                    errorText = "服务器异常";
                }
                ToastUtil.showLong(errorText);
            }
        });
    }

    /**
     * 根据Http的response中关于状态码的描述，自定义生成本地的Exception
     *
     * @param resourceObservable
     * @param <T>
     * @return
     */
    private <T extends Object> Observable<T> wrapperObject(Observable<T> resourceObservable) {
        return resourceObservable.flatMap(new Function<T, ObservableSource<? extends T>>() {
            @Override
            public ObservableSource<? extends T> apply(@NonNull final T baseResponse) throws
                    Exception {
                return Observable.create(new ObservableOnSubscribe<T>() {
                    @Override
                    public void subscribe(@NonNull ObservableEmitter<T> e) throws Exception {
                        if (baseResponse == null) {

                        } else {
                            e.onNext(baseResponse);
                        }
                    }
                });
            }
        }).doOnError(new Consumer<Throwable>() {
            @Override
            public void accept(@NonNull Throwable e) throws Exception {
                e.printStackTrace();
                String errorText = "";
                if (e instanceof retrofit2.adapter.rxjava2.HttpException) {
                    retrofit2.adapter.rxjava2.HttpException exception = (retrofit2.adapter.rxjava2.HttpException) e;
                } else if (e instanceof UnknownHostException) {
                    Logger.i("请打开网络");
                    errorText = "请打开网络";
                } else if (e instanceof SocketTimeoutException) {
                    Logger.i("请求超时");
                    errorText = "请求超时";
                } else if (e instanceof ConnectException) {
                    Logger.i("连接失败");
                    errorText = "连接失败";
                } else if (e instanceof HttpException) {
                    Logger.i("请求超时");
                    errorText = "请求超时";
                } else {
                    Logger.i("请求失败");
                    errorText = "请求失败";
                }
            }
        });
    }

}
